﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using EnvDTE;
using System.ComponentModel.Design;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Shell;
using System.Xml;
using Microsoft.VisualStudio.Shell.Design;
using System.Reflection;

namespace Ebc.DesignerDsl.CustomCode
{
    public class TypeHelper
    {
        public Type FindType(ITypeDescriptorContext context, string fullName)
        {
            DynamicTypeService typeService = (DynamicTypeService)context.GetService(typeof(DynamicTypeService));

            DTE vs = (DTE)context.GetService(typeof(DTE));
            Project project = vs.SelectedItems.Item(1).ProjectItem.ContainingProject;

            string projectGuid = null;
            using (XmlReader projectReader = XmlReader.Create(project.FileName))
            {
                projectReader.MoveToContent();
                object nodeName = projectReader.NameTable.Add("ProjectGuid");
                while (projectReader.Read())
                {
                    if (Object.Equals(projectReader.LocalName, nodeName))
                    {
                        projectGuid = projectReader.ReadElementContentAsString();
                        break;
                    }
                }
            }

            IServiceProvider serviceProvider = new ServiceProvider(project.DTE as
                Microsoft.VisualStudio.OLE.Interop.IServiceProvider);

            IVsHierarchy hier = VsShellUtilities.GetHierarchy(serviceProvider, new Guid(projectGuid));

            ITypeDiscoveryService discovery = typeService.GetTypeDiscoveryService(hier);

            object pvar = null;
            hier.GetProperty(0xfffffffe, -2027, out pvar);
            Project dteProject = (Project)pvar;

            var foundAssemblies = new List<Assembly>();

            foreach (Type type in discovery.GetTypes(typeof(object), false))
            {
                if (!foundAssemblies.Contains(type.Assembly))
                {
                    foundAssemblies.Add(type.Assembly);
                }
            }

            foreach (var item in foundAssemblies)
            {
                try
                {
                    var result = item.GetType(fullName, false);

                    if (result != null)
                    {
                        return result;
                    }
                }
                catch
                {}
            }

            return null;
        }
    }
}